package net.csdn.business.auth.facade;

import cn.hutool.core.collection.CollectionUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.csdn.business.common.domain.request.oauth.OauthAccessTokenQuery;
import net.csdn.business.common.domain.request.oauth.OauthRevokeAllDTO;
import net.csdn.business.common.domain.request.oauth.OauthRevokeDTO;
import net.csdn.business.common.domain.vo.oauth.OauthAccessTokenVO;
import net.csdn.business.common.domain.vo.oauth.OauthClientInfoVo;
import net.csdn.business.common.enums.ResultCodeEnum;
import net.csdn.business.common.exception.BusinessException;
import net.csdn.business.common.oauth2.component.CustomRedisTokenStore;
import net.csdn.business.common.oauth2.model.entity.OauthAccessToken;
import net.csdn.business.common.oauth2.service.IOauthAccessTokenService;
import net.csdn.business.common.oauth2.service.IOauthClientInfoService;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.util.SerializationUtils;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @Auther: zhangyalei
 * @Date: 2023/2/3 18:48
 * @Description:
 */

@Slf4j
@Component
@RequiredArgsConstructor
public class AuthFacade {

    private final IOauthAccessTokenService oauthAccessTokenService;

    private final CustomRedisTokenStore customRedisTokenStore;

    private final IOauthClientInfoService oauthClientInfoService;

    private final ThreadPoolTaskExecutor taskExecutor;
    /**
     * 根据userId、clientId撤销用户对此client的授权
     *
     * @param params
     * @return 结果
     */
    public Integer revoke(OauthRevokeDTO params){
        String clientId=params.getClientId();
        String currenUserName = params.getCurrUserName();
        OauthClientInfoVo clientInfoVo = oauthClientInfoService.selectClientByClientId(clientId,true);
        if (clientInfoVo == null) {
            throw new BusinessException(ResultCodeEnum.OAUTH_CLIENT_ID_ERROR);
        }
        //根据clientId、userId查询当前用户已经在此应用产生的acessToken,异步执行删除;
        taskExecutor.execute(()->{
            OauthAccessTokenQuery query=new OauthAccessTokenQuery();
            query.setUserName(currenUserName);
            query.setClientId(clientId);
            List<OauthAccessTokenVO> oauthAccessTokens=oauthAccessTokenService.selectOauthAccessTokenList(query);
            if(CollectionUtil.isEmpty(oauthAccessTokens)){
                return;
            }
            for (OauthAccessTokenVO oauthAccessToken : oauthAccessTokens) {
                OAuth2AccessToken readAccessToken= SerializationUtils.deserialize(oauthAccessToken.getToken());
                customRedisTokenStore.removeAccessToken(readAccessToken);
            }
        });
        return 1;
    }


    /**
     * 根据clientId撤销该应用所有授权
     *
     * @param params clientId：客户端id; currUserId:当前操作用户id
     * @return 结果
     */
    public Integer revokeAll(OauthRevokeAllDTO params){
        // 需要应用创建人，才有权限删除
        String clientId=params.getClientId();
        String currenUserId = params.getCurrUserId();
        OauthClientInfoVo clientInfoVo = oauthClientInfoService.selectClientByClientId(clientId,true);
        if (clientInfoVo == null) {
            throw new BusinessException(ResultCodeEnum.OAUTH_CLIENT_ID_ERROR);
        }
        if (!currenUserId.equals(clientInfoVo.getCreatedBy())) {
            throw new BusinessException(ResultCodeEnum.OAUTH_CLIENT_REVOKE_ALL_ERROR);
        }
        //异步执行删除
        taskExecutor.execute(()->{
            OauthAccessTokenQuery query=new OauthAccessTokenQuery();
            query.setClientId(clientId);
            List<OauthAccessTokenVO> oauthAccessTokens=oauthAccessTokenService.selectOauthAccessTokenList(query);
            if(CollectionUtil.isEmpty(oauthAccessTokens)){
                return;
            }
            for (OauthAccessTokenVO oauthAccessToken : oauthAccessTokens) {
                OAuth2AccessToken readAccessToken= SerializationUtils.deserialize(oauthAccessToken.getToken());
                customRedisTokenStore.removeAccessToken(readAccessToken);
            }
        });
        return 1;
    }
}
